from datetime import datetime, timedelta
from flask import Blueprint, request, jsonify
from app.models.device import Device
from app.models.air_data_stats import AirDataStats
from app.models.mongodb import mongodb
from app.models.mysql_db import db
from app.utils.logger import get_logger
from app.utils.auth import auth_required
from bson import ObjectId

logger = get_logger(__name__)

# 创建蓝图
dashboard_bp = Blueprint('dashboard', __name__, url_prefix='/api/dashboard')

def calculate_aqi(pm25):
    """根据PM2.5计算AQI"""
    if pm25 is None or pm25 <= 0:
        return 0
    elif pm25 <= 35:
        return pm25 * 50 / 35
    elif pm25 <= 75:
        return 50 + (pm25 - 35) * 50 / 40
    elif pm25 <= 115:
        return 100 + (pm25 - 75) * 50 / 40
    elif pm25 <= 150:
        return 150 + (pm25 - 115) * 50 / 35
    elif pm25 <= 250:
        return 200 + (pm25 - 150) * 100 / 100
    else:
        return 300 + (pm25 - 250) * 200 / 250

def get_air_quality_level(aqi):
    """根据AQI获取空气质量等级"""
    if aqi <= 50:
        return '优'
    elif aqi <= 100:
        return '良'
    elif aqi <= 150:
        return '轻度污染'
    elif aqi <= 200:
        return '中度污染'
    elif aqi <= 300:
        return '重度污染'
    else:
        return '严重污染'

@dashboard_bp.route('/', methods=['GET'])
@auth_required  # 添加认证装饰器
def get_dashboard_data():
    """获取仪表板基础数据"""
    try:
        # 获取所有活跃设备
        devices = Device.query.filter_by(status='active').all()
        device_count = len(devices)
          # 获取最新空气质量数据
        latest_data = []
        if device_count > 0:
            for device in devices[:5]:  # 限制显示前5个设备
                latest_record = mongodb.db.environment_data.find_one(
                    {'deviceId': device.device_id},
                    sort=[('timestamp', -1)]
                )
                if latest_record:
                    pm25 = latest_record.get('data', {}).get('pm25', 0) or 0
                    aqi = calculate_aqi(pm25)
                    latest_data.append({
                        'deviceId': device.device_id,
                        'deviceName': device.name,
                        'pm25': pm25,
                        'aqi': round(aqi, 1),
                        'level': get_air_quality_level(aqi),
                        'timestamp': latest_record.get('timestamp', 0)
                    })
        
        return jsonify({
            'code': 200,
            'message': '获取成功',
            'data': {
                'deviceCount': device_count,
                'latestData': latest_data,
                'timestamp': int(datetime.now().timestamp())
            }
        })
        
    except Exception as e:
        logger.error(f"获取仪表板数据失败: {str(e)}")
        return jsonify({'code': 500, 'message': f'获取数据失败: {str(e)}'}), 500

@dashboard_bp.route('/overview', methods=['GET'])
@auth_required
def get_dashboard_overview():
    """获取仪表板概览数据"""
    try:
        # 获取设备统计
        total_devices = Device.query.count()
        active_devices = Device.query.filter_by(status='active').count()
        offline_devices = total_devices - active_devices
        
        # 获取在线设备（最近5分钟有活动）
        five_minutes_ago = datetime.utcnow() - timedelta(minutes=5)
        online_devices = Device.query.filter(
            Device.last_online >= five_minutes_ago,
            Device.status == 'active'
        ).count()
        
        # 获取今日数据统计
        today_start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        today_timestamp = int(today_start.timestamp())
          # 从MongoDB获取今日数据量
        today_data_count = mongodb.db.environment_data.count_documents({
            'timestamp': {'$gte': today_timestamp}
        })
        
        # 计算平均空气质量
        pipeline = [
            {'$match': {'timestamp': {'$gte': today_timestamp}}},
            {'$group': {
                '_id': None,
                'avgPm25': {'$avg': '$data.pm25'},
                'avgPm10': {'$avg': '$data.pm10'},
                'avgTemperature': {'$avg': '$data.temperature'},
                'avgHumidity': {'$avg': '$data.humidity'},
                'maxPm25': {'$max': '$data.pm25'},
                'minPm25': {'$min': '$data.pm25'}
            }}
        ]
        
        avg_result = list(mongodb.db.environment_data.aggregate(pipeline))
        avg_data = avg_result[0] if avg_result else {}
        
        avg_pm25 = avg_data.get('avgPm25', 0) or 0
        avg_aqi = calculate_aqi(avg_pm25)
          # 获取告警统计（可以根据实际需求调整）
        alert_count = mongodb.db.environment_data.count_documents({
            'timestamp': {'$gte': today_timestamp},
            'data.pm25': {'$gt': 75}  # PM2.5超过75认为是告警
        })
        
        return jsonify({
            'code': 200,
            'message': '获取成功',
            'data': {
                'deviceStats': {
                    'total': total_devices,
                    'online': online_devices,
                    'offline': offline_devices,
                    'active': active_devices
                },
                'airQuality': {
                    'avgAqi': round(avg_aqi, 1),
                    'level': get_air_quality_level(avg_aqi),
                    'avgPm25': round(avg_pm25, 1),
                    'avgPm10': round(avg_data.get('avgPm10', 0) or 0, 1),
                    'maxPm25': round(avg_data.get('maxPm25', 0) or 0, 1),
                    'minPm25': round(avg_data.get('minPm25', 0) or 0, 1)
                },
                'environment': {
                    'avgTemperature': round(avg_data.get('avgTemperature', 0) or 0, 1),
                    'avgHumidity': round(avg_data.get('avgHumidity', 0) or 0, 1)
                },
                'dataStats': {
                    'todayCount': today_data_count,
                    'alertCount': alert_count
                },
                'timestamp': int(datetime.now().timestamp())
            }
        })
        
    except Exception as e:
        logger.error(f"获取概览数据失败: {str(e)}")
        return jsonify({'code': 500, 'message': f'获取概览数据失败: {str(e)}'}), 500

@dashboard_bp.route('/latestData', methods=['GET'])
def get_latest_air_data():
    """获取最新的空气质量数据"""
    try:
        # 获取查询参数
        limit = int(request.args.get('limit', 10))
        device_id = request.args.get('deviceId')
        
        # 构建查询条件
        query = {}
        if device_id:
            query['deviceId'] = device_id
          # 获取最新数据
        latest_records = mongodb.db.environment_data.find(
            query,
            sort=[('timestamp', -1)],
            limit=limit
        )
        
        # 处理数据
        data_list = []
        for record in latest_records:
            pm25 = record.get('data', {}).get('pm25', 0) or 0
            aqi = calculate_aqi(pm25)
            
            # 获取设备信息
            device = Device.query.filter_by(device_id=record.get('deviceId')).first()
            device_name = device.name if device else f"Device_{record.get('deviceId')}"
            
            data_list.append({
                'id': str(record.get('_id')),
                'deviceId': record.get('deviceId'),
                'deviceName': device_name,
                'pm25': pm25,
                'pm10': record.get('data', {}).get('pm10', 0) or 0,
                'temperature': record.get('data', {}).get('temperature', 0) or 0,
                'humidity': record.get('data', {}).get('humidity', 0) or 0,
                'aqi': round(aqi, 1),
                'level': get_air_quality_level(aqi),
                'timestamp': record.get('timestamp', 0),
                'datetime': datetime.fromtimestamp(record.get('timestamp', 0)).strftime('%Y-%m-%d %H:%M:%S')
            })
        
        return jsonify({
            'code': 200,
            'message': '获取成功',
            'data': data_list
        })
        
    except Exception as e:
        logger.error(f"获取最新数据失败: {str(e)}")
        return jsonify({'code': 500, 'message': f'获取最新数据失败: {str(e)}'}), 500

@dashboard_bp.route('/deviceStats', methods=['GET'])
def get_device_stats():
    """获取设备统计数据"""
    try:
        # 获取所有设备
        devices = Device.query.all()
        
        # 计算设备状态统计
        total_devices = len(devices)
        active_devices = Device.query.filter_by(status='active').count()
        inactive_devices = total_devices - active_devices
        
        # 获取在线设备（最近5分钟有活动）
        five_minutes_ago = datetime.utcnow() - timedelta(minutes=5)
        online_devices = Device.query.filter(
            Device.last_online >= five_minutes_ago,
            Device.status == 'active'
        ).count()
        offline_devices = active_devices - online_devices
        
        # 获取每个设备的详细信息
        device_details = []
        for device in devices:            # 获取设备最新数据
            latest_record = mongodb.db.environment_data.find_one(
                {'deviceId': device.device_id},
                sort=[('timestamp', -1)]
            )
            
            # 获取设备今日数据量
            today_start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
            today_timestamp = int(today_start.timestamp())
            today_count = mongodb.db.environment_data.count_documents({
                'deviceId': device.device_id,
                'timestamp': {'$gte': today_timestamp}
            })
            
            # 判断设备在线状态
            is_online = (device.last_online and 
                        device.last_online >= five_minutes_ago and 
                        device.status == 'active')
            
            device_info = {
                'deviceId': device.device_id,
                'name': device.name,
                'status': device.status,
                'isOnline': is_online,
                'lastOnline': device.last_online.isoformat() if device.last_online else None,
                'todayDataCount': today_count,
                'createdAt': device.created_at.isoformat() if device.created_at else None
            }
              # 添加最新数据信息
            if latest_record:
                pm25 = latest_record.get('data', {}).get('pm25', 0) or 0
                aqi = calculate_aqi(pm25)
                device_info.update({
                    'latestData': {
                        'pm25': pm25,
                        'aqi': round(aqi, 1),
                        'level': get_air_quality_level(aqi),
                        'timestamp': latest_record.get('timestamp', 0)
                    }
                })
            
            device_details.append(device_info)
        
        return jsonify({
            'code': 200,
            'message': '获取成功',
            'data': {
                'summary': {
                    'total': total_devices,
                    'active': active_devices,
                    'inactive': inactive_devices,
                    'online': online_devices,
                    'offline': offline_devices
                },
                'devices': device_details
            }
        })
        
    except Exception as e:
        logger.error(f"获取设备统计失败: {str(e)}")
        return jsonify({'code': 500, 'message': f'获取设备统计失败: {str(e)}'}), 500

@dashboard_bp.route('/airQualityStats', methods=['GET'])
def get_air_quality_stats():
    """获取空气质量统计数据"""
    try:
        # 获取时间范围参数
        days = int(request.args.get('days', 7))  # 默认最近7天
        
        # 计算开始时间
        start_date = datetime.now() - timedelta(days=days)
        start_timestamp = int(start_date.timestamp())
          # 从MongoDB获取统计数据
        pipeline = [
            {'$match': {'timestamp': {'$gte': start_timestamp}}},
            {'$group': {
                '_id': None,
                'avgPm25': {'$avg': '$data.pm25'},
                'avgPm10': {'$avg': '$data.pm10'},
                'maxPm25': {'$max': '$data.pm25'},
                'minPm25': {'$min': '$data.pm25'},
                'maxPm10': {'$max': '$data.pm10'},
                'minPm10': {'$min': '$data.pm10'},
                'count': {'$sum': 1}
            }}
        ]
        
        result = list(mongodb.db.environment_data.aggregate(pipeline))
        stats = result[0] if result else {}
        
        avg_pm25 = stats.get('avgPm25', 0) or 0
        avg_aqi = calculate_aqi(avg_pm25)
          # 按等级统计
        level_pipeline = [
            {'$match': {'timestamp': {'$gte': start_timestamp}}},
            {'$project': {
                'pm25': '$data.pm25',
                'aqi': {'$switch': {
                    'branches': [
                        {'case': {'$lte': ['$data.pm25', 35]}, 'then': {'$multiply': ['$data.pm25', 1.43]}},
                        {'case': {'$lte': ['$data.pm25', 75]}, 'then': {'$add': [50, {'$multiply': [{'$subtract': ['$data.pm25', 35]}, 1.25]}]}},
                        {'case': {'$lte': ['$data.pm25', 115]}, 'then': {'$add': [100, {'$multiply': [{'$subtract': ['$data.pm25', 75]}, 1.25]}]}},
                        {'case': {'$lte': ['$data.pm25', 150]}, 'then': {'$add': [150, {'$multiply': [{'$subtract': ['$data.pm25', 115]}, 1.43]}]}},
                        {'case': {'$lte': ['$data.pm25', 250]}, 'then': {'$add': [200, {'$subtract': ['$data.pm25', 150]}]}},
                    ],
                    'default': {'$add': [300, {'$multiply': [{'$subtract': ['$data.pm25', 250]}, 0.8]}]}
                }}
            }},
            {'$bucket': {
                'groupBy': '$aqi',
                'boundaries': [0, 51, 101, 151, 201, 301, 500],
                'default': 'other',
                'output': {'count': {'$sum': 1}}
            }}
        ]
        
        level_result = list(mongodb.db.environment_data.aggregate(level_pipeline))
        
        # 处理等级统计结果
        level_stats = {
            '优': 0,
            '良': 0,
            '轻度污染': 0,
            '中度污染': 0,
            '重度污染': 0,
            '严重污染': 0
        }
        
        level_mapping = {
            0: '优',
            51: '良',
            101: '轻度污染',
            151: '中度污染',
            201: '重度污染',
            301: '严重污染'
        }
        
        for item in level_result:
            level_name = level_mapping.get(item['_id'], '其他')
            if level_name in level_stats:
                level_stats[level_name] = item['count']
        
        return jsonify({
            'code': 200,
            'message': '获取成功',
            'data': {
                'overview': {
                    'avgAqi': round(avg_aqi, 1),
                    'level': get_air_quality_level(avg_aqi),
                    'avgPm25': round(avg_pm25, 1),
                    'avgPm10': round(stats.get('avgPm10', 0) or 0, 1),
                    'maxPm25': round(stats.get('maxPm25', 0) or 0, 1),
                    'minPm25': round(stats.get('minPm25', 0) or 0, 1),
                    'maxPm10': round(stats.get('maxPm10', 0) or 0, 1),
                    'minPm10': round(stats.get('minPm10', 0) or 0, 1),
                    'totalRecords': stats.get('count', 0)
                },
                'levelStats': level_stats,
                'period': f'最近{days}天'
            }
        })
        
    except Exception as e:
        logger.error(f"获取空气质量统计失败: {str(e)}")
        return jsonify({'code': 500, 'message': f'获取空气质量统计失败: {str(e)}'}), 500

@dashboard_bp.route('/trends', methods=['GET'])
def get_trend_data():
    """获取趋势数据"""
    try:
        # 获取参数
        hours = int(request.args.get('hours', 24))  # 默认最近24小时
        device_id = request.args.get('deviceId')
        
        # 计算开始时间
        start_time = datetime.now() - timedelta(hours=hours)
        start_timestamp = int(start_time.timestamp())
        
        # 构建查询条件
        match_condition = {'timestamp': {'$gte': start_timestamp}}
        if device_id:
            match_condition['deviceId'] = device_id
          # 按小时分组统计
        pipeline = [
            {'$match': match_condition},
            {'$project': {
                'hour': {
                    '$dateToString': {
                        'format': '%Y-%m-%d %H:00:00',
                        'date': {'$toDate': {'$multiply': ['$timestamp', 1000]}}
                    }
                },                'pm25': '$data.pm25',
                'pm10': '$data.pm10',
                'temperature': '$data.temperature',
                'humidity': '$data.humidity',
                'deviceId': 1
            }},
            {'$group': {
                '_id': '$hour',
                'avgPm25': {'$avg': '$pm25'},
                'avgPm10': {'$avg': '$pm10'},
                'avgTemperature': {'$avg': '$temperature'},
                'avgHumidity': {'$avg': '$humidity'},
                'count': {'$sum': 1}
            }},
            {'$sort': {'_id': 1}}
        ]
        
        result = list(mongodb.db.environment_data.aggregate(pipeline))
        
        # 处理趋势数据
        trend_data = []
        for item in result:
            avg_pm25 = item.get('avgPm25', 0) or 0
            aqi = calculate_aqi(avg_pm25)
            
            trend_data.append({
                'time': item['_id'],
                'pm25': round(avg_pm25, 1),
                'pm10': round(item.get('avgPm10', 0) or 0, 1),
                'temperature': round(item.get('avgTemperature', 0) or 0, 1),
                'humidity': round(item.get('avgHumidity', 0) or 0, 1),
                'aqi': round(aqi, 1),
                'level': get_air_quality_level(aqi),
                'count': item.get('count', 0)
            })
        
        return jsonify({
            'code': 200,
            'message': '获取成功',
            'data': {
                'trends': trend_data,
                'period': f'最近{hours}小时',
                'deviceId': device_id
            }
        })
        
    except Exception as e:
        logger.error(f"获取趋势数据失败: {str(e)}")
        return jsonify({'code': 500, 'message': f'获取趋势数据失败: {str(e)}'}), 500

@dashboard_bp.route('/recent-activities', methods=['GET'])
def get_recent_activities():
    """获取最近活动数据"""
    try:
        limit = int(request.args.get('limit', 20))
        
        # 获取最近的设备上线活动
        recent_devices = Device.query.filter(
            Device.last_online.isnot(None)
        ).order_by(Device.last_online.desc()).limit(limit).all()
        
        activities = []
        for device in recent_devices:            # 获取设备最新数据
            latest_record = mongodb.db.environment_data.find_one(
                {'deviceId': device.device_id},
                sort=[('timestamp', -1)]
            )
            
            activity_type = 'device_online'
            description = f"设备 {device.name} 上线"
            
            if latest_record:
                pm25 = latest_record.get('data', {}).get('pm25', 0) or 0
                if pm25 > 75:
                    activity_type = 'alert'
                    description = f"设备 {device.name} 检测到空气质量异常 (PM2.5: {pm25})"
                elif pm25 > 35:
                    activity_type = 'warning'
                    description = f"设备 {device.name} 检测到空气质量轻度污染 (PM2.5: {pm25})"
            
            activities.append({
                'id': f"device_{device.id}_{int(device.last_online.timestamp())}",
                'type': activity_type,
                'title': description,
                'deviceId': device.device_id,
                'deviceName': device.name,
                'timestamp': int(device.last_online.timestamp()),
                'datetime': device.last_online.strftime('%Y-%m-%d %H:%M:%S')
            })
        
        return jsonify({
            'code': 200,
            'message': '获取成功',
            'data': activities
        })
        
    except Exception as e:
        logger.error(f"获取最近活动失败: {str(e)}")
        return jsonify({'code': 500, 'message': f'获取最近活动失败: {str(e)}'}), 500